package com.kgc.scd.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.gson.JsonObject;
import com.kgc.scd.Constant.AccountMQConstant;
import com.kgc.scd.Constant.WechatPayConstant;
import com.kgc.scd.config.WechatPayConfig;
import com.kgc.scd.entity.ShopOrder;
import com.kgc.scd.service.WechatPayService;
import com.kgc.scd.util.HttpClient4Util;
import com.kgc.scd.util.RedisUtils;
import com.kgc.scd.util.WechatPayUtil;
import com.kgc.scd.vo.ShopOrderVO;
import com.kgc.scd.vo.ShopOrderitemVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import net.sf.json.JSONObject;
import springfox.documentation.annotations.ApiIgnore;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * Created On : 2022/11/3.
 * <p>
 * Author : zhukang
 * <p>
 * Description: 微信支付业务接口实现类
 */
@Slf4j
@Service
public class WechatPayServiceImpl implements WechatPayService {

    @Autowired
    private WechatPayConfig wechatPayConfig;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public String generateWxpayUnifyOrderXmlParams(Map<String,String> msgMap,int orderPrice) throws Exception {
        // 微信支付接口签名参数要求：
        // 特别注意以下重要规则：参数名ASCII码从小到大排序（字典序）；如果参数的值为空不参与签名；参数名区分大小写；

        // 定义微信支付接口参数集合：TreeMap(自动根据集合中的key安装字典序排序，可以满足要求)
        Map<String, String> paramsMap = new TreeMap<>();

        // 公众账号ID-appid
        paramsMap.put("appid", wechatPayConfig.getAppId());

        // 商户号
        paramsMap.put("mch_id", wechatPayConfig.getMchId());

        // 设备号,PC网页或公众号内支付可以传"WEB"
        paramsMap.put("device_info", "WEB");

        // 随机字符串，长度要求在32位以内
        paramsMap.put("nonce_str", WechatPayUtil.generateNonceStr());

        // 商品描述，对支付商品信息的简单描述，可以使用当前系统的商品名称
        paramsMap.put("body", msgMap.get("goodName"));

/*        JSONObject mapObject=JSONObject.fromObject(msgMap);
        log.info("impl:"+mapObject);*/
        // 附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用
        paramsMap.put("attach", msgMap.get("orderId"));

        // 商户订单号，商户系统内部订单号，要求32个字符内（最少6个字符），只能是数字、大小写字母_-|*且在同一个商户号下唯一
        paramsMap.put("out_trade_no", WechatPayUtil.generateTradeOrderNo());

        // 标价金额，订单总金额，单位为分，就是付款金额
        paramsMap.put("total_fee", String.valueOf(orderPrice));

        // 终端IP,支持IPV4和IPV6两种格式的IP地址
        paramsMap.put("spbill_create_ip", "192.168.1.173");

        // 通知地址，异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数。
        paramsMap.put("notify_url", wechatPayConfig.getNotifyUri());

        // 交易类型，NATIVE - Native支付
        paramsMap.put("trade_type", WechatPayConstant.WECHAT_PAY_TRADE_TYPE_NATIVE);

        // 商品ID，trade_type=NATIVE时，此参数必传。此参数为二维码中包含的商品ID，商户自行定义。
        paramsMap.put("product_id", "互联网架构师");

        // 签名，传送的sign参数不参与签名，传给微信支付接口，会将生成的签名与该sign值作校验，如果不一致，签名失败
        // 切记：签名都是在确定好接口参数后，执行签名操作，并将签名的结果加入参数集合
        paramsMap.put("sign", WechatPayUtil.generateSignature(paramsMap, wechatPayConfig.getMchKey()));

        // 将微信支付统一下单接口集合参数转换为xml字符串
        return WechatPayUtil.generateMapToXml(paramsMap);
    }

    @Override
    public Map<String, String> getWechatPayUnifyOrderResult(String unifyOrderXmlParams) throws Exception {

        // 使用post请求，请求微信支付统一下单接口，下预支付订单，并获取下单结果
        String unifyOrderXmlResult = HttpClient4Util.getResponse4PostByString(wechatPayConfig.getOrderUri(), unifyOrderXmlParams, WechatPayConstant.WECHAT_PAY_ENCODING_UTF8);

        // 将微信支付统一下单接口返回的xml格式字符串，转换为map集合返回
        return WechatPayUtil.generateXmlToMap(unifyOrderXmlResult);
    }

    @Override
    public String getReturnWechatXmlResult(String wxpayNotifyXmlResult) throws Exception {

        // 将微信支付结果通知的xml格式字符串，转换为map集合，方便处理
        Map<String, String> wxpayNotifyMapResult = WechatPayUtil.generateXmlToMap(wxpayNotifyXmlResult);

        // 解析回调结果
        if(WechatPayConstant.WECHAT_PAY_RESULT_SUCCESS.equals(wxpayNotifyMapResult.get("return_code"))){
            // 官方提醒：商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致，防止数据泄露导致出现“假通知”，造成资金损失。
            if(WechatPayUtil.isSignatureValid(wxpayNotifyMapResult, wechatPayConfig.getMchKey())){
                // 签名校验成功，说明回调结果是可信的，就可以进行业务处理，如果签名失败，说明回调来源不可信，不能进行业务处理
                // TODO 真实业务中，收到正确回调，就要进行对应的业务处理，比如修改订单状态，发送主题消息，给定用户加积分，给物流生成物流单等等

                // 支付成功，发送主题消息，给订单中心修改订单状态
                log.info("++++++ 发送广播消息：通知订单支付成功 ++++++");
                Map<String, Object> payResultMap = new HashMap<>();
                payResultMap.put("result", WechatPayConstant.WECHAT_PAY_RESULT_SUCCESS);
                payResultMap.put("orderId", wxpayNotifyMapResult.get("attach"));

                // 发送广播消息,进行结算
                //todo 判断是否是热销商品
                rabbitTemplate.convertAndSend(AccountMQConstant.NORMAL_PAY_RESULT_EXCHANGE_TEST, null, payResultMap);

                //结算
                //从回调结果中拿到orderId,goodName
                //异步修改商品库存
/*                String msgStr=wxpayNotifyMapResult.get("attach");
                JSONObject msgObject=JSONObject.fromObject(msgStr);
                Map<String,String> getMsgMap=msgObject;
                log.info("impl"+getMsgMap);
                String orderId=getMsgMap.get("orderId");
                ShopOrderVO shopOrderVO=JSON.parseObject(redisUtils.get(orderId).toString(),ShopOrderVO.class);*/


                // 业务处理成功后，需要同步给微信响应结果-成功
                return WechatPayConstant.WECHAT_PAY_NOTIFY_RESP_SUCCESS;
            }
        }

        // 同步给微信响应结果-失败
        return WechatPayConstant.WECHAT_PAY_NOTIFY_RESP_FAIL;
    }
}
